#include "rtthread.h"
#include <rtdevice.h>
#include "zino.h"
#include "buzzer.h"

#define DBG_TAG "buzzer"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>

#define pwm_dev_name "pwm1"
#define MOTOR_DEV_NAME "motor"
#define MOTOR_DEFAULT_FREQ 50000
#define MOTOR_DEFAULT_DUTY_RANGE 1000

const uint16_t freq_table[]={
    261,
    293,
    329,
    349,
    392,
    440,
    493,

    523,
    587,
    659,
    698,
    783,
    880,
    987,

    1046,
    1174,
    1318,
    1396,
    1567,
    1760,
    1975,

    2093,
    2349,
    2637,
    2793,
    3135,
    3520,
    3951,

    4186,
    4698,
    5274,
};

struct rt_device_pwm* buzzer_dev = RT_NULL;
const uint8_t boot_tone[] = {
    DO_L, RE_L, MI_L, 
};
int buzzer_init()
{
    buzzer_dev = (struct rt_device_pwm*)rt_device_find(pwm_dev_name);
    if (buzzer_dev == RT_NULL)
    {
        LOG_E("Can't find pwm device %s", pwm_dev_name);
        return -RT_ERROR;
    }
    LOG_I("Init buzzer success!");
    rt_thread_mdelay(500);
    buzzer_play_note(boot_tone, sizeof(boot_tone));
    // uint32_t peroid = 1000000000UL / zinoMotor.freq;
    // rt_pwm_set(buzzer_dev, 1, freq_table[0], MOTOR_DEFAULT_FREQ);
    return  RT_EOK;
}
void buzzer_set_freq(uint16_t freq)
{
    if (buzzer_dev == RT_NULL)
    {
        LOG_E("Init buzzer first!");
        return;
    }
    uint32_t period = 1000000000UL / freq;
    LOG_D("%dHz-%dus\n", freq, period);
    rt_pwm_set(buzzer_dev, 1, period, period/2);
    rt_pwm_enable(buzzer_dev, 1);
}
void buzzer_play_note(const uint8_t *note, uint16_t len)
{
    if (buzzer_dev == RT_NULL)
    {
        LOG_E("Init buzzer first!");
        return;
    }
    for (int i = 0; i < len; i++)
    {
        uint16_t delay = ((*note>>5) + 1)*250;
        buzzer_set_freq(freq_table[(*note ) & 0x1f]);
        rt_thread_mdelay(delay);
        note++;
    }
    rt_pwm_disable(buzzer_dev, 1);
}

void buzzer(int argc, char *argv[])
{
    if(argc == 1)
    {
        rt_kprintf("Usage: buzzer <freq> <freq> ...\n");
        return;
    }
    for(uint16_t i = 1; i < (argc); i++)
    {
        uint8_t freq = atoi(argv[i]);
        uint16_t delay = ((freq>>5) + 1)*250;
        buzzer_set_freq(freq_table[freq & 0x1f]);
        rt_thread_mdelay(delay);
        rt_pwm_disable(buzzer_dev, 1);
    }

}

ZINO_APP_EXPORT(buzzer_init);
MSH_CMD_EXPORT(buzzer, freq play);